package com.xfunc.ok.dmhttp;

import android.content.Context;
import android.net.Uri;
import android.os.Handler;
import java.io.File;
import java.security.InvalidParameterException;

/**
 * This class used to handles long-running HTTP downloads, User can raise a {@link DownloadRequest} request with multiple features.
 * The download manager will conduct the download in the background, taking care of HTTP interactions, failures  and retrying downloads
 * across connectivity changes.
 *
 * @author Mani Selvaraj
 * @author Praveen Kumar
 */
public class ThinDownloadManager implements DownloadManager {

    /**
     * Download request queue takes care of handling the request based on priority.
     */
    private DownloadRequestQueue mRequestQueue;

    /**
     * Default constructor
     */
    private ThinDownloadManager() {
        this(true);
    }

    private static class INSTANCE{
      static ThinDownloadManager instance = new ThinDownloadManager();
    }

    public static ThinDownloadManager getInstance(){
        return INSTANCE.instance;
    }

    /**
     * Construct with logging Enabled.
     * @param loggingEnabled - enable log info
     */
    private ThinDownloadManager(boolean loggingEnabled) {
        mRequestQueue = new DownloadRequestQueue();
        mRequestQueue.start();
        setLoggingEnabled(loggingEnabled);
    }

    /**
     * Construct with provided callback handler
     *
     * @param callbackHandler - callback handler
     */
    public ThinDownloadManager(Handler callbackHandler) throws InvalidParameterException {
        mRequestQueue = new DownloadRequestQueue(callbackHandler);
        mRequestQueue.start();
        setLoggingEnabled(true);
    }

    /**
     * Constructor taking MAX THREAD POOL SIZE  Allows maximum of 4 threads.
     * Any number higher than four or less than one wont be respected.
     *
     * Deprecated use Default Constructor. As the thread pool size will not respected anymore through this constructor.
     * Thread pool size is determined with the number of available processors on the device.
     **/
    public ThinDownloadManager(int threadPoolSize) {
        mRequestQueue = new DownloadRequestQueue(threadPoolSize);
        mRequestQueue.start();
        setLoggingEnabled(true);
    }

    /**
     * Add a new download.  The download will start automatically once the download manager is
     * ready to execute it and connectivity is available.
     *
     * @param request the parameters specifying this download
     * @return an ID for the download, unique across the application.  This ID is used to make future
     * calls related to this download.
     * @throws IllegalArgumentException
     */
    @Override
    public int add(DownloadRequest request) throws IllegalArgumentException {
        checkReleased("add(...) called on a released ThinDownloadManager.");
        if (request == null) {
            throw new IllegalArgumentException("DownloadRequest cannot be null");
        }
        return mRequestQueue.add(request);
    }
    public int add(Context context, String fileUrl){
        Log.d("download>>>",fileUrl);
        if(checkRequestUrl(fileUrl)<0){
            return -1;
        }
        String fileFullName = getFileFullPathFromUrl(context,fileUrl);
//        File skinFile = new File(fileFullName);
//        if (skinFile.exists()) {
//            boolean delete = skinFile.delete();
//            Log.d("download-存在文件删除",fileFullName);
//        }
        Uri downloadUri = Uri.parse(fileUrl);
        Uri destinationUri = Uri.parse(fileFullName);
        DownloadRequest downloadRequest = new DownloadRequest(downloadUri)
                .setRetryPolicy(new DefaultRetryPolicy())
                .setDestinationURI(destinationUri)
                .setDownloadResumable(true)
                .setPriority(DownloadRequest.Priority.HIGH);
        downloadRequest.setStatusListener(new DownloadStatusListenerV1() {
            @Override
            public void onDownloadComplete(DownloadRequest downloadRequest) {
//                EventBusManager.post(
//                        new EventDMBean(DownloadManager.STATUS_SUCCESSFUL,downloadRequest.getDownloadId(),
//                        downloadRequest.getContentLength(),downloadRequest.getDownloadedBytes(),100));
            }
            @Override
            public void onDownloadFailed(DownloadRequest downloadRequest, int errorCode, String errorMessage) {
                int progress = 0;
                if(downloadRequest.getContentLength()!=0){
                     progress = (int) ((downloadRequest.getDownloadedBytes() * 100) / downloadRequest.getContentLength());
                }
//                EventBusManager.post(
//                        new EventDMBean(DownloadManager.STATUS_FAILED,downloadRequest.getDownloadId(),
//                                downloadRequest.getContentLength(),downloadRequest.getDownloadedBytes(),progress));
            }
            @Override
            public void onProgress(DownloadRequest downloadRequest, long totalBytes, long downloadedBytes, int progress) {
//                EventBusManager.post(
//                        new EventDMBean(downloadRequest.getDownloadState(),downloadRequest.getDownloadId(),
//                        totalBytes,downloadedBytes,progress));
            }
        });
        return add(downloadRequest);
    }
    public int checkRequestUrl(String fileUrl){
        if(fileUrl==null||fileUrl.isEmpty()){
            Log.d("download>>>","下载地址不能为空");
            return -10000;
        }
        if(!fileUrl.startsWith("http")||!fileUrl.contains(".")){
            Log.d("download>>>","下载地址错误");
            return -10001;
        }
        //检查如果存在相同request url 则不进行下载
        if(mRequestQueue.isSampleRequest(fileUrl)){
            Log.d("download>>>","正在下载中");
            return -1002;
        }
        return 1;
    }
    public String getFileFullPathFromUrl(Context context,String fileUrl){
        String filePath = AppFilePathUtils.getFilesDir(context,"dm");
        String fileName = getFileNameFromUrl(fileUrl);
        String skinFullName = String.format("%s%s%s", filePath, File.separator, fileName);
        Log.d("download-获取文件地址："+filePath+"  \n "+skinFullName);
        return skinFullName;
    }
    public String getFileNameFromUrl(String fileUrl){
        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        int pos = fileName.indexOf('?');
        if (pos > 0) {
            fileName = fileName.substring(0, pos);
        }
        Log.d("获取文件名",fileName);
        return fileName;
    }

    @Override
    public int cancel(int downloadId) {
        checkReleased("cancel(...) called on a released ThinDownloadManager.");
        return mRequestQueue.cancel(downloadId);
    }

    @Override
    public void cancelAll() {
        checkReleased("cancelAll() called on a released ThinDownloadManager.");
        mRequestQueue.cancelAll();
    }

    @Override
    public int pause(int downloadId) {
        Log.d("download>>>","暂停下载 "+downloadId);
        checkReleased("pause(...) called on a released ThinDownloadManager.");
        return mRequestQueue.pause(downloadId);
    }
    public int delete(int downloadId,String filePath){
        pause(downloadId);
        File file = new File(filePath);
        file.delete();
        return 1;
    }

    @Override
    public void pauseAll() {
        checkReleased("pauseAll() called on a released ThinDownloadManager.");
        mRequestQueue.pauseAll();
    }

    @Override
    public int query(int downloadId) {
        checkReleased("query(...) called on a released ThinDownloadManager.");
        return mRequestQueue.query(downloadId);
    }

    @Override
    public void release() {
        if (!isReleased()) {
            mRequestQueue.release();
            mRequestQueue = null;
        }
    }

    @Override
    public boolean isReleased() {
        return mRequestQueue == null;
    }

    /**
     * This is called by methods that want to throw an exception if the DownloadManager
     * has already been released.
     */
    private void checkReleased(String errorMessage) {
        if (isReleased()) {
            throw new IllegalStateException(errorMessage);
        }
    }

    private static void setLoggingEnabled(boolean enabled) {
        Log.setEnabled(enabled);
    }
}


